package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.AccountUser;
import com.tbit.uqbike.object.pojo.AdoptMachineBound;
import com.tbit.uqbike.object.pojo.Machine;
import com.tbit.uqbike.object.pojo.dto.CommonDTO;
import com.tbit.uqbike.object.pojo.vo.BatchOperationMsgVO;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.business.AdoptMachineBoundService;
import com.tbit.uqbike.webmanager.dao.core.AccountUserDao;
import com.tbit.uqbike.webmanager.dao.core.AdoptMachineBoundDao;
import com.tbit.uqbike.webmanager.dao.core.MachineDao;
import com.tbit.uqbike.webmanager.util.DateUtils;
import com.tbit.uqbike.webmanager.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: chen
 * @Description: 领养模式
 * @Date: 创建于 10:28 2020/8/14
 */
@Service
public class AdoptMachineBoundServiceImpl implements AdoptMachineBoundService {

    @Autowired
    private AdoptMachineBoundDao adoptMachineBoundDao;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private AccountUserDao accountUserDao;

    @Override
    public List<AdoptMachineBound> queryPage(String name, String userCode, Integer accountId, Integer accountUserId,
                                             Integer pageNO, Integer rowCount) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "%" + name + "%");
        map.put("userCode", userCode);
        map.put("accountUserId", accountUserId);
        map.put("accountId", accountId);
        map.put("pageNO", (pageNO - 1) * rowCount);
        map.put("rowCount", rowCount);
        return adoptMachineBoundDao.queryPage(map);
    }

    @Override
    public Integer queryCount(String name, String userCode, Integer accountId, Integer accountUserId) {
        Map<String, Object> map = new HashMap<>(8);
        map.put("name", "%" + name + "%");
        map.put("userCode", userCode);
        map.put("accountId", accountId);
        map.put("accountUserId", accountUserId);
        return adoptMachineBoundDao.queryCount(map);
    }

    @Override
    public Map<String, Object> insert(AdoptMachineBound adoptMachineBound, List<String> userCode) {
        AccountUser accountUser = accountUserDao.getAccountUserById(adoptMachineBound.getAccountUserId());
        if (accountUser == null) {
            throw new BaseException("account_not_exist");
        }
        List<Machine> machines = machineDao.checkUserCodeExist(userCode);
        Map<Integer, Object> existMachine = new HashMap<>(8);
        List<String> notExistMachine = new ArrayList<>();
        List<Integer> existMachine1 = new ArrayList<>();
        Map<String, Object> maps = new HashMap<>(8);
        userCode.forEach(code -> {
            boolean flag = false;
            for (Machine machine : machines) {
                if (code.equals(machine.getUserCode())) {
                    existMachine.put(machine.getMachineId(), machine.getUserCode());
                    existMachine1.add(machine.getMachineId());
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                notExistMachine.add(code);
            }
        });
        if (StringUtils.isNotEmpty(notExistMachine)) {
            maps.put("notExistMachine", notExistMachine);
        }
        List<AdoptMachineBound> notExistAdopt = new ArrayList<>();
        List<String> existAdoptMachine = new ArrayList<>();
        /**是否存在*/
        if (StringUtils.isNotEmpty(existMachine1)) {
            List<AdoptMachineBound> existAdopt = adoptMachineBoundDao.getIsExist(existMachine1);
            existMachine1.forEach(exist -> {
                boolean flag = false;
                for (AdoptMachineBound adopt : existAdopt) {
                    if (exist.equals(adopt.getMachineId())) {
                        existAdoptMachine.add((String) existMachine.get(exist));
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    AdoptMachineBound ad = new AdoptMachineBound();
                    ad.setAccountUserId(adoptMachineBound.getAccountUserId());
                    ad.setBoundTime(DateUtils.getNowDate());
                    ad.setMachineId(exist);
                    notExistAdopt.add(ad);
                }
            });
        }
        if (StringUtils.isNotEmpty(existAdoptMachine)) {
            maps.put("boundMachine", existAdoptMachine);
        }
        if (StringUtils.isNotEmpty(notExistAdopt)) {
            adoptMachineBoundDao.insert(notExistAdopt);
        }
        return maps;
    }

    @Override
    public void del(AdoptMachineBound adoptMachineBound) {
        adoptMachineBoundDao.del(adoptMachineBound);
    }

    @Override
    public List<CommonDTO> getAdoptMoney(Integer accountUserId, Long startTime, Long endTime) {
        Map<String, Object> map = new HashMap<>(5);
        map.put("accountUserId", accountUserId);
        map.put("startTime", new Date(startTime));
        map.put("endTime", new Date(endTime));
        List<CommonDTO> commonDTOList = adoptMachineBoundDao.getadoptEarnings(map);
        commonDTOList.forEach(commonDTO -> {
            commonDTO.setMoney(commonDTO.getMoney() / 100);
        });
        return commonDTOList;
    }

    /**
     * 批量删除领养人车辆
     * @param adoptMachineBound adoptMachineBound
     */
    @Override
    public Result<BatchOperationMsgVO> batchDel(AdoptMachineBound adoptMachineBound) {
        BatchOperationMsgVO vo = new BatchOperationMsgVO();

        if (Objects.isNull(adoptMachineBound.getBrandId())){
            return Result.error("请选择品牌");
        }

        if (CollectionUtil.isEmpty(adoptMachineBound.getUserCodes())){
            return Result.error("请选择需要删除的设备");
        }

        //获取已存在设备信息 转成map key:machineId value:userCode
        List<Machine> machineList = machineDao.selectByUserCodes(adoptMachineBound.getUserCodes(),adoptMachineBound.getBrandId());
        Map<Integer, String> machineIdMap = machineList.stream()
                .collect(Collectors.toMap(Machine::getMachineId, Machine::getUserCode));


        Set<String> inDbUserCodeList = machineList.stream()
                .map(Machine::getUserCode)
                .collect(Collectors.toSet());


        if (CollectionUtil.isEmpty(machineList)){
            vo.setNoExitList(adoptMachineBound.getUserCodes());
            return Result.success(vo);
        }

        //不存在的设备编号
        List<String> noExitList = adoptMachineBound.getUserCodes()
                .stream().filter(userCode -> !inDbUserCodeList.contains(userCode))
                .collect(Collectors.toList());

        //校验是否绑定领养人
        List<Integer> idDbMacheIdList = adoptMachineBoundDao.selectByMachineId(adoptMachineBound.getAccountUserId());

        if (CollectionUtil.isEmpty(idDbMacheIdList)){
            vo.setNoExitList(noExitList);
            vo.setFailList(Arrays.asList(inDbUserCodeList.toArray()));
            return Result.success(vo);
        }

        List<Integer> machineIdList = machineList.stream()
                .map(Machine::getMachineId)
                .collect(Collectors.toList());
        //未绑定领养人设备
        List<Integer> failList = machineIdList.stream()
                .filter(a -> !idDbMacheIdList.contains(a))
                .collect(Collectors.toList());

        List<Integer> success = machineIdList.stream()
                .filter(a -> idDbMacheIdList.contains(a))
                .collect(Collectors.toList());

        List<String> failUserCodeList = failList.stream()
                .map(machineIdMap::get)
                .collect(Collectors.toList());


        if (CollectionUtil.isNotEmpty(success)){
            adoptMachineBoundDao.batchDel(adoptMachineBound.getAccountUserId(), success);
        }

        vo.setSuccessList(success.stream().map(machineIdMap::get).collect(Collectors.toList()));
        vo.setNoExitList(noExitList);
        vo.setFailList(failUserCodeList);
        return Result.success(vo);
    }
}
